using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
//#define HZ_2_MEL(f) 1127.0*log(1.0 + f/700.0)
//#define MEL_2_HZ(m) 700.0*(exp(m/1127.0) - 1.0)
//#define HZ_2_BARK(f) 13.0*atan(0.00076*f) + 3.5*atan(f*f/56250000)
//#define BARK_2_HZ(b) 52548/(b*b - 52.567 + 690.39)
//#define HZ_2_ERBS(f) 21.4*log10(0.00437*f+1)
//#define ERBS_2_HZ(e) (pow(10.0, e/21.4) - 1)/0.00437

    class Program
    {
        delegate double forward_t(double f);
        delegate double backward_t(double z);

        static double HZ_2_MEL(double f)
        {
            return 1127.0*Math.Log(1.0 + f/700.0);
        }

        static double MEL_2_HZ(double m)
        {
            return 700.0*(Math.Exp(m/1127.0) - 1.0);
        }

        static double HZ_2_ERBS(double f)
        {
            return 21.4 * Math.Log10(0.00437 * f + 1);
        }

        static double ERBS_2_HZ(double z)
        {
            return (Math.Pow(10.0, z / 21.4) - 1) / 0.00437;
        }

        static double HZ_2_BARK(double f)
        {
            return (26.81 / (1.0 + 1960.0 / f)) - 0.53;
        }

        static double BARK_2_HZ(double z)
        {
            return 1960.0 / (26.81 / (z + 0.53) - 1);
        }

        static double[] getBand(int min_f, int max_f, int bandsNum, forward_t transform, backward_t inverse)
        {
            double[] bands = new double[bandsNum+1];

            double z_min = transform(min_f);
            double z_max = transform(max_f);

            double step = (z_max - z_min) / (bandsNum);
            double z = z_min;
            for (int i = 0; i < bandsNum; i++)
            {
                bands[i] = inverse(z);
                z += step;
            }
            bands[bandsNum] = inverse(z_max);

            return bands;
        }

        //! use this
        /*!
         \param type 0 - MEL, 1 - ERBS
         */
        static double[] getBand(int min_f, int max_f, int bandsNum, int type)
        {

            switch (type)
            {
                case 0:
                    return getBand(min_f, max_f, bandsNum, new forward_t(HZ_2_MEL), new backward_t(MEL_2_HZ));
                case 1:
                    return getBand(min_f, max_f, bandsNum, new forward_t(HZ_2_ERBS), new backward_t(ERBS_2_HZ));
                case 2:
                    return getBand(min_f, max_f, bandsNum, new forward_t(HZ_2_BARK), new backward_t(BARK_2_HZ));
            }

            return new double[1];
        }

        //#define HZ_2_BARK(f) 13.0*atan(0.00076*f) + 3.5*atan(f*f/56250000)
        //#define BARK_2_HZ(b) 52548/(b*b - 52.567 + 690.39)
        //#define HZ_2_ERBS(f) 21.4*log10(0.00437*f+1)
        //#define ERBS_2_HZ(e) (pow(10.0, e/21.4) - 1)/0.00437

        static void Main(string[] args)
        {
            int min_f = 0;
            int max_f = 22000;
            int bandsNum = 20;

            double[] bands = getBand(min_f, max_f, bandsNum, 2);
            for(int i=0; i<bandsNum+1; i++)
            {
                System.Console.WriteLine(bands[i]);
            }
            System.Console.ReadKey();
        }
    }
}
